package aerolineasAdapters;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import aOrganizar.Aerolinea;
import aOrganizar.Asiento;
import aOrganizar.Usuario;
import aOrganizar.Vuelo;

import com.oceanic.AerolineaOceanic;
import com.oceanic.AsientoDTO;

import excepciones.ComprarException;
import excepciones.ReservarException;
import fechas.FechaUtils;

public class OceanicAdapter implements Aerolinea {

	
	private static final Double RECARGO_OCEANIC = 1.2;
	private Map<String,String> mapCiudades = new HashMap<String,String>();
	
	
	private static AerolineaOceanic aerolinea = AerolineaOceanic.getInstance();


	
	/**
	 * Constructores
	 */
	
	public OceanicAdapter() {
		this.loadMapaCiudades();
	}

	/**
	 * Compra un asiento
	 * 
	 * @param asiento
	 *            Asiento que se quiere comprar
	 * @param usuario
	 *            Asiento que se quiere reservar
	 * @throws ComprarException
	 *             Lanza una excepcion sino puede comprar el asiento
	 */

	public void comprar(Asiento asiento, Usuario user) throws ComprarException {
		Vuelo vuelo = asiento.getVuelo();
		Boolean pudoComprar = aerolinea.comprarSiHayDisponibilidad(
				user.getDni(), vuelo.getCodigo(),
				Integer.getInteger(asiento.getNumeroDeAsiento()));
		if (!pudoComprar) {
			throw new ComprarException(asiento);
		}
		return;

	}

	/**
	 * Reserva un asiento
	 * 
	 * @param asiento
	 *            Asiento que se quiere reservar
	 * @param user
	 *            Usuario que quiere reservar el asiento
	 * @throws ReservarException
	 *             Lanza una excepcion sino se puede reservar el asiento
	 */

	public void reservar(Asiento asiento, Usuario user)
			throws ReservarException {
		Vuelo vuelo = asiento.getVuelo();
		Boolean pudoReservar = aerolinea.reservar(user.getDni(),
				vuelo.getCodigo(),
				Integer.getInteger(asiento.getNumeroDeAsiento()));
		if (!pudoReservar)
			throw new ReservarException(asiento);
	}

	/**
	 * Busca asientos con origen y destino
	 * 
	 * @param origen
	 *            Lugar desde donde viaja
	 * @param destino
	 *            Lugar a donde quiere viajar
	 * @param fecha
	 *            Fecha en la que quiere viajar
	 */

	public Collection<Asiento> findAsientosByOrigenYDestino(String origen,
			String destino, Date fecha, Usuario usuario) {
		List<AsientoDTO> asientosDisponibles = aerolinea
				.asientosDisponiblesParaOrigenYDestino(
						this.getCiudad(origen), this.getCiudad(destino),
						new SimpleDateFormat("dd/MM/yyyy").format(fecha));
		return parsearAsientos(asientosDisponibles, usuario);
	}

	/**
	 * Busca asientos por origen solo
	 * 
	 * @param origen
	 *            Lugar desde donde viaja
	 * @param fecha
	 *            Fecha en la que quiere viajar
	 */

	public Collection<Asiento> findAsientosByOrigen(String origen, Date fecha,
			Usuario usuario) {
		List<AsientoDTO> asientosDisponibles = aerolinea
				.asientosDisponiblesParaOrigen(this.getCiudad(origen),
						new SimpleDateFormat("dd/MM/yyyy").format(fecha));
		return parsearAsientos(asientosDisponibles, usuario);
	}

	/**
	 * Convierte los asientos del tipo AsientoDTO a tipo Asiento
	 * 
	 * @param asientos
	 *            Es una lista de asientos tipo AsientoDTO
	 * @return Una lista de asientos tipo Asientos
	 */

	private Collection<Asiento> parsearAsientos(List<AsientoDTO> asientos,
			Usuario usuario) {
		int i = 0;
		List<Asiento> listAsientos = new ArrayList<Asiento>();
		for (i = 0; i < asientos.size(); i++) {
			AsientoDTO asientoOcea = asientos.get(i);
			Vuelo vueloaux = new Vuelo(asientoOcea.getCodigoDeVuelo(),
					this.getCiudad(asientoOcea.getOrigen()), this.getCiudad(asientoOcea.getDestino()),
					FechaUtils.fechaConHorasYMinutos(
							asientoOcea.getFechaDeLlegada(),
							asientoOcea.getHoraDeLlegada()),
					FechaUtils.fechaConHorasYMinutos(
							asientoOcea.getFechaDeSalida(),
							asientoOcea.getHoraDeSalida()), this);
			Asiento asientoAux = new Asiento(
					convertirClase(asientoOcea.getClase()),
					Integer.toString(asientoOcea.getNumeroDeAsiento()),
					(asientoOcea.getPrecio()).doubleValue(),
					convertirUbicacion(asientoOcea.getUbicacion()), vueloaux,
					convertirEstado(asientoOcea.getReservado()), usuario);
			listAsientos.add(asientoAux);
		}
		return listAsientos;
	}

	/**
	 * 
	 * @param reservado
	 *            Estado del asiento del tipo AsientoDTO
	 * @return Estado del asiento del tipo Asiento
	 */

	private String convertirEstado(Boolean reservado) {
		if (reservado == true)
			return "R";
		return "D";
	}

	/**
	 * 
	 * @param ubicacion
	 *            Ubicacion tipo AsientoDTO
	 * @return Ubicacion tipo Asiento
	 */

	private String convertirUbicacion(String ubicacion) {
		if (ubicacion == "Ventana")
			return "V";
		if (ubicacion == "Pasillo")
			return "P";
		return "C";
	}

	/**
	 * 
	 * @param clase
	 *            Clase tipo AsientoDTO
	 * @return Clase tipo Asiento
	 */

	private String convertirClase(String clase) {
		if (clase == "Primera")
			return "P";
		if (clase == "Ejecutiva")
			return "E";
		return "T";
	}
	
	private void loadMapaCiudades(){
		this.mapCiudades.put("USA", "USA");
		this.mapCiudades.put("BUE", "_BS");
		this.mapCiudades.put("_BS", "BUE");
		this.mapCiudades.put("USH", "USH");
		this.mapCiudades.put("CABA","AEO");
		this.mapCiudades.put("AEO","CABA");
		this.mapCiudades.put("LA","SLA");
		this.mapCiudades.put("SLA","LA");
		this.mapCiudades.put("NYC","_NY");
		this.mapCiudades.put("_NY","NYC");
	}
	
	public String getCiudad(String ciudad) {
		return (this.mapCiudades.get(ciudad)!=null? this.mapCiudades.get(ciudad): "");
	}	
	
	public Double getRecargo() {
		return OceanicAdapter.RECARGO_OCEANIC;
	}
	
	public String getNombre(){
		return "Oceanic";
	}
	
}